package org.chronologger.poppaea.client.widgets;

import org.chronologger.poppaea.client.domain.Person;
import org.chronologger.poppaea.client.domain.Scene;
import org.chronologger.poppaea.client.i18n.SceneWidgetConsts;
import org.chronologger.poppaea.client.utils.Pair;
import org.chronologger.poppaea.client.utils.Pair.StringWidgetPair;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.TextBoxBase;

public class SceneEditor extends ArrowPopupPanel {

	private static final int EDITOR_ARROW_X_OFFSET = 5;
	private static final int EDITOR_ARROW_Y_OFFSET = 15;
	private static final int EDITOR_CONTENT_HEIGHT = 280;
	private static final int EDITOR_CONTENT_WIDTH = 320;
	private static final SceneWidgetConsts lang = GWT
			.create(SceneWidgetConsts.class);

	private static SceneEditor instance = null;

	private final FlexTable table = new FlexTable();
	private final TextBox titleBox = new TextBox();
	private final TextArea descriptionText = new TextArea();
	private final TextArea notesBox = new TextArea();
	private final FlowPanel characterPanel = new FlowPanel();
	private final SegmentedButton submitButton = new SegmentedButton();
	private final SegmentedButton addPersonButton = new SegmentedButton();
	private final SegmentedButton colorButton = new SegmentedButton();
	
	private final Pair.StringWidgetPair rows[] = new Pair.StringWidgetPair[] {
			new Pair.StringWidgetPair(lang.title(), titleBox),
			new Pair.StringWidgetPair(lang.color(), colorButton),
			new Pair.StringWidgetPair(lang.description(), descriptionText),
			new Pair.StringWidgetPair(lang.notes(), notesBox),
			new Pair.StringWidgetPair(lang.characters(), characterPanel),
			new Pair.StringWidgetPair("", submitButton) };

	private Scene scene = null;
	private SceneWidget widget = null;

	private SceneEditor() {
		getContentPanel().addEventHandler(Event.ONDBLCLICK,
				EventHandler.doNothing);

		table.setWidth("100%");
		table.addStyleName("property-list");
		table.getColumnFormatter().setWidth(0, "100px");

		KeyDownHandler cancelActionHandler = new KeyDownHandler() {

			public void onKeyDown(KeyDownEvent event) {
				switch (event.getNativeKeyCode()) {
				case KeyCodes.KEY_ESCAPE:
					cancel();
					break;
				}
			}
		};

		KeyDownHandler saveActionHandler = new KeyDownHandler() {

			public void onKeyDown(KeyDownEvent event) {
				switch (event.getNativeKeyCode()) {
				case KeyCodes.KEY_ENTER:
					save();
					event.stopPropagation();
					event.preventDefault();
					break;
				}
			}
		};

		submitButton.setColor("gray");
		submitButton.addSegment(lang.done()).addClickHandler(
				new ClickHandler() {
					public void onClick(ClickEvent event) {
						try {
							hide(true);
						} catch(Exception e) {
							// fail
						}
					}
				});
		submitButton.getSegment(0).getElement().getStyle().setProperty(
				"fontSize", "1.1em");
		
		addPersonButton.addSegment("+");
		addPersonButton.setSegmentSize(0, 16, 16);
		
		colorButton.addSegment("").addClickHandler(ColorPicker.createClickHandler(colorButton));
		colorButton.setHoverColor("");
		colorButton.setSegmentSize(0, 16, 16);
		
		FocusWidget lastFocusWidget = null;
		for (Pair.StringWidgetPair p : rows) {
			table.setText(table.getRowCount(), 0, p.a);
			table.setWidget(table.getRowCount() - 1, 1, p.b);

			table.getCellFormatter().addStyleName(table.getRowCount() - 1, 0,
					"property-list-name");
			if (p.b instanceof FocusWidget && !(p.b instanceof Button)) {
				lastFocusWidget = (FocusWidget) p.b;
				if (lastFocusWidget instanceof TextBox) {
					lastFocusWidget.addKeyDownHandler(saveActionHandler);
				}
				lastFocusWidget.addKeyDownHandler(cancelActionHandler);
			}
		}

		addCloseHandler(new CloseHandler<PopupPanel>() {

			public void onClose(CloseEvent<PopupPanel> event) {
				if (event.isAutoClosed())
					save();
			}
		});

		getContentPanel().add(table);

		lastFocusWidget.addKeyDownHandler(new KeyDownHandler() {

			public void onKeyDown(KeyDownEvent event) {
				if (event.getNativeKeyCode() == KeyCodes.KEY_TAB) {
					titleBox.setFocus(true);
					event.preventDefault();
					event.stopPropagation();
				}
			}
		});
	}

	public static SceneEditor getInstance() {
		if (instance == null)
			instance = new SceneEditor();
		return instance;
	}

	public void setEvent(Scene scene) {
		if (scene != this.scene) {
			if (this.widget != null)
				removeAutoHidePartner(widget.getElement());
			characterPanel.clear();
			this.scene = scene;
			widget = scene.getWidget();
			addAutoHidePartner(widget.getElement());
			colorButton.setColor(scene.getColor());

			for (Person person : scene) {
				characterPanel.add(new PersonButtonWidget(scene, person));
			}
			characterPanel.add(addPersonButton);

			titleBox.setText(scene.getTitle());
			descriptionText.setText(scene.getDescription());
			notesBox.setText(scene.getNotes());
		}
		
		for(StringWidgetPair r : rows) {
			if(r.b instanceof SegmentedButton)
				((SegmentedButton)r.b).resetHoverState();
		}

		pointAt(widget.getAbsoluteLeft() + EDITOR_ARROW_X_OFFSET, widget
				.getAbsoluteLeft()
				+ widget.getOffsetWidth() - EDITOR_ARROW_X_OFFSET, widget
				.getAbsoluteTop()
				+ EDITOR_ARROW_Y_OFFSET, EDITOR_CONTENT_WIDTH,
				EDITOR_CONTENT_HEIGHT);
		titleBox.setFocus(true);
	}

	public Scene getScene() {
		return scene;
	}

	public void cancel() {
		scene = null;
		hide();
	}

	public void save() {
		updateScene();
		scene = null;
		hide();
	}

	/**
	 * updates the Scene Object with the data from the textboxes, etc.
	 */
	public void updateScene() {
		scene.setTitle(getBoxText(titleBox, scene.getTitle()));
		scene.setDescription(getBoxText(descriptionText));
		scene.setNotes(getBoxText(notesBox));
		scene.setColor(colorButton.getColor());
	}

	private static String getBoxText(TextBoxBase input, String def) {
		String newValue = input.getText().trim();
		if ((def != null) && input.equals("")) {
			return def;
		} else {
			return newValue;
		}
	}

	private static String getBoxText(TextBoxBase input) {
		return getBoxText(input, null);
	}

}
